<template>
  <div class="">
    <div id="container">
      <div id="k-line-chart" v-loading="state.loading" style="height: 350px">
        <van-overlay :show="state.loading">
          <div class="wrapper">
            <van-loading />
          </div>
        </van-overlay>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
  import { i18nTranslate } from '/@/i18n';
  import { init } from 'klinecharts';
  import {
    reactive,
    ref,
    defineProps,
    computed,
    watch,
    defineEmits,
    onDeactivated,
    onActivated,
  } from 'vue';
  import {
    getMarketChart,
    queryOpenPrice,
    getTokensKLine,
    getTickerPrice,
    getFuturesKLine,
  } from '/@/apis/userApi';
  import { jiadesocketio } from '/@/hooks/index';
  import { useRequest } from 'vue-request';
  const openPrice = ref<{ [xx: string]: any }>({});
  const isCONTRACT = ref(false);
  const typeObjMap = ref({
    '1m': {
      addTime: 60 * 60,
      selectTime: 60,
    },
    '5m': {
      addTime: 60 * 60,
      selectTime: 60,
    },
    '15m': {
      addTime: 60 * 60,
      selectTime: 60,
    },
    '30m': {
      addTime: 60 * 60,
      selectTime: 60,
    },
    '1h': {
      addTime: 60 * 60,
      selectTime: 60,
    },
    '1d': {
      addTime: 60 * 60,
      selectTime: 60,
    },
    '1wk': {
      addTime: 60 * 60,
      selectTime: 60,
    },
  });
  function queryOpenPriceparms(value: string) {
    useRequest(queryOpenPrice, {
      defaultParams: [{ pairsNames: value }],
      onSuccess(data: any) {
        if (data) {
          for (const key in data) {
            let item = data[key];
            let openPricegd = JSON.parse(item).data;

            openPrice.value = openPricegd;
          }

          emit('changezuihou', {
            open: openPrice.value.open,
            close: openPrice.value.previous_close,
          });
        }
      },
    });
  }
  // ws 推送
  function customSocketFunction(socketmessage: {
    initKline: string;
    pairName: string;
    timeType: string;
  }) {
    let aaa = JSON.parse(socketmessage.initKline);

    if (aaa.length) {
      let message = JSON.parse(aaa[aaa.length - 1]) as { [xx: string]: any };
      emit('changezuihou', {
        lastPrice: message.close.toFixed(4),
        high: Math.max(props.data.high, message.close).toFixed(4),
        low: Math.min(props.data.low, message.close).toFixed(4),
      });
      if (state.chart) {
        const dataList = state.chart.getDataList();
        const lastData = dataList[dataList.length - 1];
        const newData = { ...lastData };
        newData.close = Number(message.close.toFixed(4));
        newData.high = Math.max(newData.high, message.high.toFixed(4));
        newData.open = newData.open;
        newData.low = Math.min(newData.low, message.low.toFixed(4));

        state.chart.updateData(newData);
      }
    }
  }
  const jiadesocket = jiadesocketio();
  let timers = ref();
  function isContent() {
    return jiadesocket.socketver.readyState == 1;
  }
  function sendjiadeline() {
    let customdate = new Date().getTime();
    if (!isContent()) return;
    jiadesocket.socketver.send(
      `initKline-${props.queryData.name}-${props.typeObj}-${
        customdate - 1000 * 60 * 60
      }-${customdate}-${props.queryData.symbol}`,
    );
  }
  function handleUnit(value: string | number) {
    let newValue = '';
    if (Number(value) >= 1000000000) {
      newValue = (Number(value) / 1000000000).toFixed(2) + 'B';
    } else if (Number(value) < 1000000) {
      newValue = (Number(value) / 1000).toFixed(2) + 'K';
    } else {
      newValue = (Number(value) / 1000000).toFixed(2) + 'M';
    }
    return newValue;
  }
  async function queryDataOfType() {
    if (isCONTRACT.value) {
      let lastData = state.KLineList[state.KLineList.length - 1];
      useRequest(getTickerPrice, {
        defaultParams: [
          {
            symbols: props.queryData.nickName
              ? (props.queryData.nickName as string).split('/').join('')
              : (props.queryData.name as string).split('/').join(''),
            type: props.queryData.type,
          },
        ],
        onSuccess(data: any) {
          if (!JSON.parse(data).data) {
            return;
          }
          let priceData = JSON.parse(data).data[0];
          let lastKline = {
            ...lastData,
            close: Number(priceData.lastPrice || priceData.last_price),
          };
          if (
            typeObjMap.value[props.typeObj].selectTime + lastKline.timestamp <
            priceData.closeTime
          ) {
            lastKline.timestamp = priceData.closeTime;
          }
          if (props.queryData.type == 'CONTRACT') {
            state.chart.updateData(lastKline);
            emit('changezuihou', {
              low: Number(priceData.lowPrice),
              high: Number(priceData.highPrice),
              quoteVolume: handleUnit(Number(priceData.quoteVolume)),
              volume: handleUnit(Number(priceData.volume)),
              symbol: priceData.symbol.slice(0, -4),
            });
            emit('changezuihou', {
              lastPrice: lastKline.close.toFixed(4),
              chgPct: priceData.priceChangePercent + '%',
              chg: Number(priceData.priceChange).toFixed(4),
            });
          } else {
            state.chart.updateData(lastKline);
            emit('changezuihou', {
              low: Number(priceData.low_price),
              high: Number(priceData.high_price),
              // quoteVolume: handleUnit(Number(priceData.quoteVolume)),
              volume: handleUnit(Number(priceData.volume)),
              symbol: priceData.symbol,
            });
            emit('changezuihou', {
              lastPrice: lastKline.close.toFixed(4),
              chgPct: priceData.chg_pct + '%',
              chg: Number(priceData.chg).toFixed(4),
            });
          }
        },
      });
    } else {
      sendjiadeline();
    }
  }
  onDeactivated(() => {
    clearInterval(timers.value);
    timers.value = null;
  });
  onActivated(() => {
    klineXR();
  });

  function timer() {
    let timeLop = 5000;
    if (isCONTRACT.value) {
      timeLop = 1000 * 3;
    }
    queryDataOfType();
    timers.value = setInterval(queryDataOfType, timeLop);
  }
  const state = reactive<{ [xx: string]: any }>({
    chart: null,
    fullScreenchart: null,
    pid: '',
    loading: false,
    interval: '',
    symbol: '',
    dataList: [],
    current: '',
    routeData: {},
    KLineList: [],
  });
  const props = defineProps<{
    typeObj: '1m' | '5m' | '15m' | '1h' | '1d' | '1wk' | '30m';
    data: { [xx: string]: any };
    propsOptions: {
      mainIndicator: any[];
      subIndicator: any[];
    };
    queryData: { [xx: string]: any };
  }>();
  const emit = defineEmits(['current', 'changezuihou']);
  const myTypeObj = computed(() => {
    return props.typeObj;
  });
  const name = computed(() => {
    return props.queryData.name;
  });
  async function queryFuturesKLineMethod(arr: any[], tokensData: any[]) {
    await useRequest(getFuturesKLine, {
      manual: true,
    })
      .runAsync({
        symbol: props.queryData.symbol,
        interval: myTypeObj.value == '1wk' ? '1w' : myTypeObj,
      })
      .then(async (res: any) => {
        console.log(JSON.parse(res));
        if (!JSON.parse(res).data) {
          await queryFuturesKLineMethod(arr, tokensData);
          return;
        }
        tokensData = JSON.parse(res).data as any[];
        tokensData.forEach((item) => {
          arr.push({
            timestamp: item.timestamp * 1000,
            open: Number(item.open),
            close: Number(item.close),
            high: Number(item.high),
            low: Number(item.low),
            volume: Number(item.volume),
          });
        });
      });
  }
  async function queryTokenMethod(symbol: string, tokensData: any[], arr: any[]) {
    await useRequest(getTokensKLine, {
      manual: true,
    })
      .runAsync({
        symbol: symbol,
        interval: myTypeObj.value == '1wk' ? '1w' : myTypeObj,
      })
      .then(async (res: any) => {
        // abc = JSON.parse(res);
        if (!JSON.parse(res).data) {
          await queryTokenMethod(symbol, tokensData, arr);
          return;
        }
        tokensData = JSON.parse(res).data as any[];
        tokensData.forEach((item) => {
          arr.push({
            timestamp: item[6],
            open: Number(item[1]),
            close: Number(item[4]),
            high: Number(item[2]),
            low: Number(item[3]),
            volume: Number(item[5]),
          });
        });
      });
  }
  async function queryTokens() {
    console.log(props.queryData);
    let arr: any[] = [];
    let tokensData: any[] = [];
    // symbol 虚拟币和期货的区别
    let symbol = props.queryData.nickName
      ? (props.queryData.nickName as string).split('/').join('')
      : (props.queryData.name as string).split('/').join('');
    if (props.queryData.type == 'CARBON_TRADING') {
      await queryFuturesKLineMethod(arr, tokensData);
    } else {
      await queryTokenMethod(symbol, tokensData, arr);
    }

    state.KLineList = arr;
    return arr as any[];
  }
  function getTimestamp() {
    // 获取当前时间
    const now = new Date();

    // 获取当前的日期和星期
    const day = now.getDay();

    // 如果当前时间是周六（6）或周日（0）
    if (day === 6 || day === 0) {
      // 计算上一个周五的日期
      // 如果当前是周六，那么上一个周五的日期是当前日期减去 1 天
      // 如果当前是周日，那么上一个周五的日期是当前日期减去 2 天
      const daysToSubtract = day === 6 ? 1 : 2;
      now.setDate(now.getDate() - daysToSubtract);
      // 设置时间为周五晚上 8 点
      now.setHours(20, 0, 0, 0);
    }
    // 返回时间戳
    return now.getTime();
  }
  async function markChart() {
    isCONTRACT.value =
      props.queryData.type === 'CONTRACT' || props.queryData.type === 'CARBON_TRADING';
    let abc: { [xx: string]: any } = {};
    let arr: any[] = [];
    state.loading = true;
    let customdate = getTimestamp() / 1000;
    if (isCONTRACT.value) {
      arr = (await queryTokens()) as any[];
    } else {
      let startTime = parseFloat(customdate.toString().split('.')[0]) - 60 * 60 * 5;
      if (myTypeObj.value == '1wk') {
        startTime = parseFloat(customdate.toString().split('.')[0]) - 60 * 60 * 24 * 7 * 50 * 5;
      }
      if (myTypeObj.value == '1d') {
        startTime = parseFloat(customdate.toString().split('.')[0]) - 60 * 60 * 24 * 7 * 50;
      }
      if (myTypeObj.value == '1h') {
        startTime = parseFloat(customdate.toString().split('.')[0]) - 60 * 60 * 24 * 7 * 5;
      }
      if (myTypeObj.value == '30m') {
        startTime = parseFloat(customdate.toString().split('.')[0]) - 60 * 60 * 24 * 7 * 2;
      }
      if (myTypeObj.value == '5m') {
        startTime = parseFloat(customdate.toString().split('.')[0]) - 60 * 60 * 24 * 7 * 2;
      }
      await useRequest(getMarketChart, {
        manual: true,
      })
        .runAsync({
          symbol: props.queryData.symbol,
          interval: myTypeObj,
          startTime: startTime,
          endTime: parseFloat(customdate.toString().split('.')[0]) + 60 * 5,
        })
        .then((res: any) => {
          abc = JSON.parse(res).data;
        });
      const chartList = abc[0].indicators.quote[0];
      abc[0].timestamp.forEach((item: number, index: number) => {
        if (
          chartList.open[index] &&
          chartList.close[index] &&
          chartList.high[index] &&
          chartList.low[index]
        ) {
          arr.push({
            timestamp: item * 1000,
            open: Number(chartList.open[index]),
            close: Number(chartList.close[index]),
            high: Number(chartList.high[index]),
            low: Number(chartList.low[index]),
            volume: Number(chartList.volume[index]),
          });
        }
      });
      state.KLineList = arr;
      let lastData = state.KLineList[state.KLineList.length - 1];
      emit('changezuihou', {
        lastPrice: lastData.close.toFixed(4),
        open: lastData.open.toFixed(4),
        low: lastData.low.toFixed(4),
        high: lastData.high.toFixed(4),
      });
    }
    state.loading = false;
    return arr;
  }
  // 主表与附表的指标变化
  watch(
    () => props.propsOptions,
    (newVal: any) => {
      if (newVal.mainIndicator.length) {
        newVal.mainIndicator.forEach((item: any) => {
          setMainIndicator(item);
        });
      }
      if (newVal.subIndicator.length) {
        newVal.subIndicator.forEach((item: any) => {
          setSubIndicator(item);
        });
      }
    },
    {
      deep: true,
      immediate: true,
    },
  );
  //切换外汇，虚拟币，期货
  watch(
    () => props.queryData,
    (newVal: any) => {
      localStorage.setItem('trade', JSON.stringify(props.queryData));
      if (Object.values(newVal).length > 0) {
        isCONTRACT.value =
          props.queryData.type === 'CONTRACT' || props.queryData.type === 'CARBON_TRADING';
        if (!isCONTRACT.value) {
          queryOpenPriceparms(props.queryData.name as string);
          jiadesocket.getMixinWs(customSocketFunction);
        }
        clearInterval(timers.value);
        timers.value = null;

        timer();
      }
    },
    {
      immediate: true,
    },
  );
  watch(
    () => myTypeObj,
    async () => {
      if (state.chart) {
        let data = await markChart();
        handleData();
        setType();
        state.chart.applyNewData(data);
        return;
      }
    },
    {
      deep: true,
      immediate: true,
    },
  );
  watch(
    () => name,
    async () => {
      if (!name.value) {
        return;
      }

      if (state.chart) {
        let data = await markChart();
        handleData();
        state.chart.applyNewData(data);
        return;
      }
      state.pid = props.queryData.pid;
      const now = new Date();
      const year = now.getFullYear(); // 获取当前年份
      const month = now.getMonth() + 1 > 10 ? now.getMonth() + 1 : '0' + (now.getMonth() + 1); // 获取当前月份，注意getMonth()返回的是0-11，所以需要加1
      const day = now.getDate() - 1 > 10 ? now.getDate() - 1 : '0' + (now.getDate() - 1); // 获取当前日期
      state.current = year + '-' + month + '-' + day;
      let data = await markChart();
      handleData();
      initChart(data);
    },
    {
      deep: true,
      immediate: true,
    },
  );
  async function klineXR() {
    if (state.chart) {
      let data = await markChart();
      handleData();
      state.chart.applyNewData(data);
      return;
    }
    let data = await markChart();
    handleData();
    initChart(data);
  }
  function initChart(data: any, height = 100) {
    state.chart = init('k-line-chart');
    setType();
    state.chart.applyNewData(data);
    state.chart.setZoomEnabled(true);
    state.chart.setTimezone(i18nTranslate('Timezone'));
    state.chart.setScrollEnabled(true);
    state.chart.setPriceVolumePrecision(4);
    state.chart.createIndicator(
      'DMI',
      false,
      {
        id: 'pane_1',
        height: height,
        minHeight: 30,
        dragEnabled: true,
        gap: { top: 0.2, bottom: 0.1 },
        axisOptions: { scrollZoomEnabled: true },
      },
      () => {},
    );
  }
  function setType() {
    let chartStyle = {} as { [xx: string]: any };

    if (myTypeObj.value === '1m') {
      chartStyle = {
        grid: {
          show: true,
          horizontal: {
            show: true,
            color: 'rgba(255, 255, 255, 0.2)',
          },
          vertical: {
            show: true,
            color: 'rgba(255, 255, 255, 0.2)',
          }
        },
        xAxis: {
          show: true,
          // x轴线
          axisLine: {
            show: true,
            color: 'rgba(255, 255, 255, 0.2)',
          },
          tickLine: {
            show: false,
          }
        },
        yAxis: {
          show: true,
          // x轴线
          axisLine: {
            show: true,
            color: 'rgba(255, 255, 255, 0.2)',
          },
          tickLine: {
            show: false,
          }
        },
        // 主表附表分割线
        separator: {
          color: 'rgba(255, 255, 255, 0.3)',
        },
        candle: {
          type: 'area',
          tooltip: {
            custom: [
              {
                title: 'time',
                value: {
                  text: '{time}',
                  color: 'red',
                },
              },
              {
                title: 'open',
                value: {
                  text: '{open}',
                  color: 'red',
                },
              },
              {
                title: 'high',
                value: {
                  text: '{high}',
                  color: 'red',
                },
              },
              {
                title: 'low',
                value: {
                  text: '{low}',
                  color: 'red',
                },
              },
              {
                title: 'close',
                value: {
                  text: '{close}',
                  color: 'red',
                },
              },
              {
                title: 'volume',
                value: {
                  text: '{volume}',
                  color: 'red',
                },
              },
            ],
            defaultValue: 'n/a',
            text: {
              size: 8,
              family: 'Helvetica Neue',
            },
            icons: [],
          },
        },
      };
    } else {
      chartStyle = {
        grid: {
          show: true,
          horizontal: {
            show: true,
            color: 'rgba(255, 255, 255, 0.2)',
          },
          vertical: {
            show: true,
            color: 'rgba(255, 255, 255, 0.2)',
          }
        },
        xAxis: {
          show: true,
          // x轴线
          axisLine: {
            show: true,
            color: 'rgba(255, 255, 255, 0.2)',
          },
        },
        yAxis: {
          show: true,
          // x轴线
          axisLine: {
            show: true,
            color: 'rgba(255, 255, 255, 0.2)',
          },
        },
        // 主表附表分割线
        separator: {
          color: 'rgba(255, 255, 255, 0.3)',
        },
        candle: {
          type: 'candle_solid',
          bar: {
            upColor: '#4CA335',
            downColor: '#FF5D5F',
            noChangeColor: '#888888',
            upBorderColor: '#4CA335',
            downBorderColor: '#FF5D5F',
            noChangeBorderColor: '#888888',
            upWickColor: '#4CA335',
            downWickColor: '#FF5D5F',
            noChangeWickColor: '#888888',
          },
          tooltip: {
            offsetLeft: 0,
            offsetTop: 6,
            custom: [
              {
                title: 'time',
                value: {
                  text: '{time}',
                  color: 'red',
                },
              },
              {
                title: 'open',
                value: {
                  text: '{open}',
                  color: 'red',
                },
              },
              {
                title: 'high',
                value: {
                  text: '{high}',
                  color: 'red',
                },
              },
              {
                title: 'low',
                value: {
                  text: '{low}',
                  color: 'red',
                },
              },
              {
                title: 'close',
                value: {
                  text: '{close}',
                  color: 'red',
                },
              },
              {
                title: 'volume',
                value: {
                  text: '{volume}',
                  color: 'red',
                },
              },
            ],
            defaultValue: 'n/a',
            text: {
              size: 8,
              family: 'Helvetica Neue',
              weight: 'normal',
              color: '#fff',
            },
            icons: [],
          },
          priceMark: {
            show: true,
            // 最新价标记
            last: {
              show: true,
              upColor: '#4CA335',
              downColor: '#FF5D5F',
              noChangeColor: '#888888',
              line: {
                show: true,
                // 'solid' | 'dashed'
                style: 'dashed',
                dashedValue: [4, 4],
                size: 1,
              },
            },
          },
        },

        // },
      };
    }
    state.chart.setStyles(chartStyle);
  }
  //处理数据
  function handleData() {
    let unfishtObjData = state.dataList[state.dataList.length - 1];
    emit('current', unfishtObjData);
  }
  function setMainIndicator(name: string) {
    state.chart.createIndicator(name, false, { id: 'candle_pane' });
  }

  function setSubIndicator(name: string) {
    state.chart.createIndicator(name, false, { id: 'pane_1' });
  }
</script>
<style scoped>
  .van-overlay {
    z-index: 100 !important;
  }

  .wrapper {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
  }

  .fullScreenclass {
    width: 100vw;
    height: 100vh;
  }
</style>
